#include <stdio.h>
#include <ctype.h>

/*
 * __ctype_b_loc
 *
 *      单字节类型判断
 */

#if 0

/* These are defined in ctype-info.c.
   The declarations here must match those in localeinfo.h. */

/* __ctype_b_loc 申明 */
extern const unsigned short int **__ctype_b_loc (void)
     __THROW __attribute__ ((__const__));

/* __isctype 宏定义，调用__ctype_b_loc */
# define __isctype(c, type) \
  ((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) type)

/* 大小端转换 */
# include <bits/endian.h>
# if __BYTE_ORDER == __BIG_ENDIAN
#  define _ISbit(bit)	(1 << (bit))
# else /* __BYTE_ORDER == __LITTLE_ENDIAN */
#  define _ISbit(bit)	((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8))
# endif

/* 枚举值 */
enum
{
  _ISupper = _ISbit (0),	/* UPPERCASE.  */
  _ISlower = _ISbit (1),	/* lowercase.  */
  _ISalpha = _ISbit (2),	/* Alphabetic.  */
  _ISdigit = _ISbit (3),	/* Numeric.  */
  _ISxdigit = _ISbit (4),	/* Hexadecimal numeric.  */
  _ISspace = _ISbit (5),	/* Whitespace.  */
  _ISprint = _ISbit (6),	/* Printing.  */
  _ISgraph = _ISbit (7),	/* Graphical.  */
  _ISblank = _ISbit (8),	/* Blank (usually SPC and TAB).  */
  _IScntrl = _ISbit (9),	/* Control character.  */
  _ISpunct = _ISbit (10),	/* Punctuation.  */
  _ISalnum = _ISbit (11)	/* Alphanumeric.  */
};


#define	__exctype(name)	extern int name (int) __THROW
__exctype (isdigit);    /* extern int isdigit (int) __THROW ---> isdigit 函数申明 */

/* isdigit 函数定义， 调用 __isctype， __isctype 再调用 __ctype_b_loc */
# define isdigit(c)	__isctype((c), _ISdigit)        /* (*__ctype_b_loc ())[(int) (c)] & _ISdigit */

#endif

int main()
{
    printf("0x%x\n", _ISdigit);        /* 0x800 */

    printf("0x%x\n", isdigit('1'));    /* 0x800 */
    printf("0x%x\n", isdigit('-'));    /* 0x0 */

    return 0;
}

#if 0
/*
 * intel
 */
0000000000001169 <main>:
    1169:	f3 0f 1e fa          	endbr64 
    116d:	55                   	push   %rbp
    116e:	48 89 e5             	mov    %rsp,%rbp
    1171:	be 00 08 00 00       	mov    $0x800,%esi          // 0x800
    1176:	48 8d 3d 87 0e 00 00 	lea    0xe87(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>  // rdi="0x%x\n" 
    117d:	b8 00 00 00 00       	mov    $0x0,%eax
    1182:	e8 d9 fe ff ff       	callq  1060 <printf@plt>    // printf(rdi, rsi)
    1187:	e8 e4 fe ff ff       	callq  1070 <__ctype_b_loc@plt> // rax=0x7ffff7fac4d8   --> **__ctype_b_loc
                                                                    // 0x7ffff7fac4d8: 0x7ffff7f553c0
                                                                    
    118c:	48 8b 00             	mov    (%rax),%rax              // rax=0x7ffff7f553c0 --> *__ctype_b_loc
                                                                    // 0x7ffff7f553c0 <_nl_C_LC_CTYPE_class+256>:  0x0002000200020002

    118f:	48 83 c0 62          	add    $0x62,%rax               // rax=0x7ffff7f553c0+0x62=0x7ffff7f55422 --> *__ctype_b_loc+0x62
                                                                    // 0x7ffff7f55422 <_nl_C_LC_CTYPE_class+354>:  0xd808d808d808d808
    
    1193:	0f b7 00             	movzwl (%rax),%eax              // eax=0xd808   --> __ctype_b_loc+0x62
    1196:	0f b7 c0             	movzwl %ax,%eax                 // ax=0xd808, eax=ax=0xd808
    1199:	25 00 08 00 00       	and    $0x800,%eax              // eax=0xd808 & 0x800 = 0x800
    119e:	89 c6                	mov    %eax,%esi                // esi=eax
    11a0:	48 8d 3d 5d 0e 00 00 	lea    0xe5d(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>  // rdi="0x%x\n" 
    11a7:	b8 00 00 00 00       	mov    $0x0,%eax
    11ac:	e8 af fe ff ff       	callq  1060 <printf@plt>        // printf(rdi, esi)

    11b1:	e8 ba fe ff ff       	callq  1070 <__ctype_b_loc@plt> // rax=0x7ffff7fac4d8
                                                                    // 0x7ffff7fac4d8:0x7ffff7f553c0

    11b6:	48 8b 00             	mov    (%rax),%rax              // rax=0x7ffff7f553c0
                                                                    // 0x7ffff7f553c0 <_nl_C_LC_CTYPE_class+256>:  0x0002000200020002

    11b9:	48 83 c0 5a          	add    $0x5a,%rax               // rax=0x7ffff7f553c0+0x5a = 0x7ffff7f5541a
                                                                    // 0x7ffff7f5541a <_nl_C_LC_CTYPE_class+346>:  0xd808c004c004c004

    11bd:	0f b7 00             	movzwl (%rax),%eax              // eax=0xc004
    11c0:	0f b7 c0             	movzwl %ax,%eax                 // eax=0xc004   ah=0xc0, al=0x04
    11c3:	25 00 08 00 00       	and    $0x800,%eax              // eax = 0xc004 & 0x800 = 0x0
    11c8:	89 c6                	mov    %eax,%esi
    11ca:	48 8d 3d 33 0e 00 00 	lea    0xe33(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    11d1:	b8 00 00 00 00       	mov    $0x0,%eax
    11d6:	e8 85 fe ff ff       	callq  1060 <printf@plt>
    11db:	b8 00 00 00 00       	mov    $0x0,%eax
    11e0:	5d                   	pop    %rbp
    11e1:	c3                   	retq   
    11e2:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
    11e9:	00 00 00 
    11ec:	0f 1f 40 00          	nopl   0x0(%rax)
#endif

#if 0

__ctype_b_loc(void)

函数返回一个数组，其中每个元素包含一个 ASCII 字符的特征。
例如，通过查找表格，我们可以了解到字符“A”是大写的、十六进制的、图形的、打印的、字母数字的。

__ctype_b_loc()

函数返回一个 const unsigned short int** ，它是一个指向384个 unsigned short int* 的数组的指针。 
有 ara 384 个元素的原因是表格可以通过以下方式索引：

    任何 unsigned char 值[0,255]（所以256个元素） EOF (-1)  any  signed char 值 [-128,-1) （所以 127 个元素）

此表由函数使用：

    上
    更慢
    isalpha
    正点
    ...

但是这些函数被定义为宏，所以你永远不会看到它们在汇编代码中被调用。

您将看到调用 __ctype_b_loc() 来获取表项，一些代码来检索正确的条目，以及使用位掩码来查看我们正在检查的属性是否已设置。
例如，如果我们想查看一个字符是否为大写，我们必须检查位 0 是否已设置。

这里是调用 isupper('A'); 生成的汇编代码：

call sym.imp.__ctype_b_loc  ; isupper('A');
mov rax, qword [rax]        ; get the pointer to the array of 'unsigned short int*'
movsx rdx, byte 0x41        ; prepare to look up for character 'A'
add rdx, rdx                ; each entry is 2 bytes, so we double the value of 'A'
add rax, rdx                ; look up for 'A' in the table
movzx eax, word [rax]       ; get the 'unsigned short int' containing the properties
movzx eax, ax               
and eax, 0x100              ; 0x0100 in little-endian is 0x0001 in big-endian (check if bit 0 is set)


const short unsigned int** __ctype_b_loc()
{
    static short unsigned int** ret = 0;
    if (ret != 0)
    {
        return (const short unsigned int**)ret;
    }
    int len = sizeof(ctype_b_values)/sizeof(short unsigned int);
    int i;
    short unsigned int* lookupTable = (short unsigned int*)malloc(len*sizeof(short unsigned int));
    for (i = 0; i < len; i++)
    {
        lookupTable[i] = ctype_b_values[i];
    }
    ret = (short unsigned int**)malloc(sizeof(short unsigned int*));
    *ret = lookupTable;
    return (const short unsigned int**)ret;
}

short unsigned int ctype_b_values[]={
0x0002, // 
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x2003, //  
0x2002, //
0x2002, //
0x2002, //
0x2002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, 
0x0002, 
0x0002, 
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x0002, //
0x6001, // 
0xc004, //!
0xc004, //"
0xc004, //#
0xc004, //$
0xc004, //%
0xc004, //&
0xc004, //'
0xc004, //(
0xc004, //)
0xc004, //*
0xc004, //+
0xc004, //,
0xc004, //-
0xc004, //.
0xc004, ///
0xd808, //0
0xd808, //1
0xd808, //2
0xd808, //3
0xd808, //4
0xd808, //5
0xd808, //6
0xd808, //7
0xd808, //8
0xd808, //9
0xc004, //:
0xc004, //;
0xc004, //<
0xc004, //=
0xc004, //>
0xc004, //?
0xc004, //@
0xd508, //A
0xd508, //B
0xd508, //C
0xd508, //D
0xd508, //E
0xd508, //F
0xc508, //G
0xc508, //H
0xc508, //I
0xc508, //J
0xc508, //K
0xc508, //L
0xc508, //M
0xc508, //N
0xc508, //O
0xc508, //P
0xc508, //Q
0xc508, //R
0xc508, //S
0xc508, //T
0xc508, //U
0xc508, //V
0xc508, //W
0xc508, //X
0xc508, //Y
0xc508, //Z
0xc004, //[
0xc004, //
0xc004, //]
0xc004, //^
0xc004, //_
0xc004, //`
0xd608, //a
0xd608, //b
0xd608, //c
0xd608, //d
0xd608, //e
0xd608, //f
0xc608, //g
0xc608, //h
0xc608, //i
0xc608, //j
0xc608, //k
0xc608, //l
0xc608, //m
0xc608, //n
0xc608, //o
0xc608, //p
0xc608, //q
0xc608, //r
0xc608, //s
0xc608, //t
0xc608, //u
0xc608, //v
0xc608, //w
0xc608, //x
0xc608, //y
0xc608, //z
0xc004, //{
0xc004, //|
0xc004, //}
0xc004, //~
0x0002, //
0x0000, //€
0x0000, //
0x0000, //‚
0x0000, //ƒ
0x0000, //„
0x0000, //…
0x0000, //†
0x0000, //‡
0x0000, //ˆ
0x0000, //‰
0x0000, //Š
0x0000, //‹
0x0000, //Œ
0x0000, //
0x0000, //Ž
0x0000, //
0x0000, //
0x0000, //‘
0x0000, //’
0x0000, //“
0x0000, //”
0x0000, //•
0x0000, //–
0x0000, //—
0x0000, //˜
0x0000, //™
0x0000, //š
0x0000, //›
0x0000, //œ
0x0000, //
0x0000, //ž
0x0000, //Ÿ
0x0000, // 
0x0000, //¡
0x0000, //¢
0x0000, //£
0x0000, //¤
0x0000, //¥
0x0000, //¦
0x0000, //§
0x0000, //¨
0x0000, //©
0x0000, //ª
0x0000, //«
0x0000, //¬
0x0000, //­
0x0000, //®
0x0000, //¯
0x0000, //°
0x0000, //±
0x0000, //²
0x0000, //³
0x0000, //´
0x0000, //µ
0x0000, //¶
0x0000, //·
0x0000, //¸
0x0000, //¹
0x0000, //º
0x0000, //»
0x0000, //¼
0x0000, //½
0x0000, //¾
0x0000, //¿
0x0000, //À
0x0000, //Á
0x0000, //Â
0x0000, //Ã
0x0000, //Ä
0x0000, //Å
0x0000, //Æ
0x0000, //Ç
0x0000, //È
0x0000, //É
0x0000, //Ê
0x0000, //Ë
0x0000, //Ì
0x0000, //Í
0x0000, //Î
0x0000, //Ï
0x0000, //Ð
0x0000, //Ñ
0x0000, //Ò
0x0000, //Ó
0x0000, //Ô
0x0000, //Õ
0x0000, //Ö
0x0000, //×
0x0000, //Ø
0x0000, //Ù
0x0000, //Ú
0x0000, //Û
0x0000, //Ü
0x0000, //Ý
0x0000, //Þ
0x0000, //ß
0x0000, //à
0x0000, //á
0x0000, //â
0x0000, //ã
0x0000, //ä
0x0000, //å
0x0000, //æ
0x0000, //ç
0x0000, //è
0x0000, //é
0x0000, //ê
0x0000, //ë
0x0000, //ì
0x0000, //í
0x0000, //î
0x0000, //ï
0x0000, //ð
0x0000, //ñ
0x0000, //ò
0x0000, //ó
0x0000, //ô
0x0000, //õ
0x0000, //ö
0x0000, //÷
0x0000, //ø
0x0000, //ù
0x0000, //ú
0x0000, //û
0x0000, //ü
0x0000, //ý
0x0000, //þ
0x0000, //ÿ
0x0020, // 
0x0000, //
0x0000, //
0x0000, //
0x0000, //
0x0000, //
0x0028, //
0x0000, //
0x0043, //
0x0000, //  
0x0029, //
0x0000, //
0x0000, //
0x0000,
0x0000, //
0x0000, //
0x003c, //
0x0000, //
0x003c, //
0x0000, //
0x0000, //
0x0000, //
0x0000, //
0x0000, 
0x002d, 
0x0000, 
0x0000, 
0x0000, 
0x0000, 
0x0000, //
0x0028, //
0x0000, //
0x0052, // 
0x0000, //!
0x0029, //"
0x0000, //#
0x0000, //$
0x0000, //%
0x0000, //&
0x0000, //'
0x0075, //(
0x0000, //)
0x0000, //*
0x0000, //+
0x0000, //,
0x0000, //-
0x002c, //.
0x0000, ///
0x0000, //0
0x0000, //1
0x0000, //2
0x0000, //3
0x003e, //4
0x0000, //5
0x003e, //6
0x0000, //7
0x0000, //8
0x0000, //9
0x0000, //:
0x0000, //;
0x0020, //<
0x0000, //=
0x0031, //>
0x0000, //?
0x002f, //@
0x0000, //A
0x0034, //B
0x0000, //C
0x0020, //D
0x0000, //E
0x0000, //F
0x0000, //G
0x0000, //H
0x0000, //I
0x0020, //J
0x0000, //K
0x0031, //L
0x0000, //M
0x002f, //N
0x0000, //O
0x0032, //P
0x0000, //Q
0x0020, //R
0x0000, //S
0x0000, //T
0x0000, //U
0x0000, //V
0x0000, //W
0x0020, //X
0x0000, //Y
0x0033, //Z
0x0000, //[
0x002f, 
0x0000, //]
0x0034, //^
0x0000, //_
0x0020, //`
0x0000, //a
0x0000, //b
0x0000, //c
0x0000, //d
0x0000, //e
0x0041, //f
0x0000, //g
0x0045, //h
0x0000, //i
0x0000, //j
0x0000, //k
0x0000, //l
0x0000, //m
0x0078, //n
0x0000, //o
0x0000, //p
0x0000, //q
0x0000, //r
0x0000, //s
0x0073, //t
0x0000, //u
0x0073, //v
0x0000, //w
0x0000, //x
0x0000, //y
0x0000, //z
0x0000, //{
0x0061, //|
0x0000, //}
0x0065, //~
0x0000, //
};


#endif